use std::cell::RefCell;
use std::marker::PhantomPinned;
use std::mem;
use std::ops::{Deref, DerefMut};
use std::pin::Pin;
use lazy_static::lazy::Lazy;
use tokio::pin;

///trait_pin: 让变量保持持有在固定位置，防止移动
///
///问题背景：在复杂的数据结构中，比如自引用，链表等结构中，需要保证在移动时值本身和指向原始值的指针也必须一同变化

///如果直接用引用类型，
/// 1.rust是值语义语言，要求值在初始化时一定要定义
/// 2.在初始化时无法直接引用自身的变量
struct SelfRef1<'a> {
    data: i32,
    ref_data: &'a i32,
}

///如果使用Option代替
#[derive(Debug)]
struct SelfRef2<'a> {
    data: i32,
    ref_data: Option<&'a i32>,
}

impl<'a> SelfRef2<'a> {
    pub fn new(data: i32) -> Self {
        let mut tmp = Self {
            data,
            ref_data: None,
        };
        //无法在借用后吧tmp移出去,(导致&tmp生命周期大于tmp)
        // tmp.ref_data = Some(&(tmp.data));

        //可以强转为指针然后移出,导致离开方法块后,引用指向地址变成随机数
        unsafe {
            tmp.ref_data = Some(&(*(&mut tmp as *mut SelfRef2)).data);
        }
        tmp
    }
}

///如果使用指针代替
struct SelfRef3 {
    data: i32,
    ptr_data: *const i32,
}

impl SelfRef3 {
    pub fn new(data: i32) -> Self {
        let mut temp = Self {
            data,
            ptr_data: std::ptr::null(),
        };
        //可以强转为指针然后移出,导致离开方法块后,引用指向地址变成随机数
        //而且在执行交换，移动，拷贝时，作为指针只会拷贝地址部分，并不会对指向地址的内容负责
        temp.ptr_data = &temp.data;
        temp
    }
}
/// 安全的自引用（本质上加一层寻址逻辑，使用指针屏蔽不完全拷贝）
/// 不安全拷贝时，值的变化：SimpleCopy{data:i32(1/0x1),ptr:*const i32(1/0x1)}->(copy)->SimpleCopy{data:i32(1/0x2),ptr:*const i32(?/0x1)}
#[derive(Debug)]
struct SafeSelfRef {
    data: i32,
    ptr_data: *const i32,
    //用来标记 !Unpin
    _pin: PhantomPinned,
}

impl SafeSelfRef {
    // 方案一采用二段式处理先定义，通过pin固定在栈内存
    pub fn new(data: i32) -> Self {
        Self {
            data,
            ptr_data: std::ptr::null(),
            _pin: PhantomPinned,
        }
    }
    pub fn init(self: Pin<&mut Self>) {
        unsafe {
            self.get_unchecked_mut().ptr_data = &self.data;
        }
    }

    // 方案二只允许构建pin数据固定在堆内存
    pub fn new_pin(data: i32) -> Pin<Box<Self>> {
        let self_ref = Self {
            data,
            ptr_data: std::ptr::null(),
            _pin: PhantomPinned,
        };
        let mut box_pin = Box::pin(self_ref);
        unsafe {
            box_pin.as_mut().get_unchecked_mut().ptr_data = &box_pin.data;
        }
        box_pin
    }
}

#[test]
fn test1() {
    let mut pin = SafeSelfRef::new_pin(1);
    println!("{:?}", pin);
    //
    // let mut new_pin = pin;
    //
    // println!("{:?}", new_pin);
    let self_ref = SafeSelfRef::new(123);
    pin!(self_ref);
    self_ref.as_mut().init();
    println!("{:?}", self_ref);
    {
        mem::swap(&mut self_ref, &mut pin.as_mut());
    }
    // println!("{:?}", pin);
    println!("{:?}", self_ref);
    unsafe {
        println!("{}", *self_ref.ptr_data);
    }
}
/// pin本质上通过添加一层指针的引用来实现最上层的浅拷贝（rust默认拷贝都是浅拷贝），从而保证内部变量交换转移都是安全的
#[test]
fn test2(){

    let safe_ref= SafeSelfRef::new(1);
    pin!(safe_ref);
    safe_ref.as_mut().init();
    println!("{:?}", safe_ref);

    let mut safe_ref2= SafeSelfRef::new(2);
    pin!(safe_ref2);
    safe_ref2.as_mut().init();

    mem::swap(&mut safe_ref2,&mut safe_ref);
    println!("{:?}", safe_ref);

}

#[test]
fn test4(){

    let cell = RefCell::new(1);
    let x = cell.as_ptr();
    let x2 = cell.as_ptr();
    unsafe {
        *x = 2;
        *x2 = 4;
    }
    println!("{:?}", cell);
    let mut ref_mut = cell.borrow_mut();
    *ref_mut = 3;
    drop(ref_mut);
    println!("{:?}", cell);

}